home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_001 / speechtoy / speechtoy.c < prev   
C/C++ Source or Header  |  1992-05-06  |  49KB  |  1,399 lines

  1. /* This program is probably copyright Commodore-Amiga.  It was mailed
  2.  * to me directly by Bruce Barrett at Commodore-Amiga in response
  3.  * to a question about a previous version's copyright status.  I
  4.  * therefore assume that it is Commodore-Amiga's intention that this
  5.  * program be freely redistributable.  Fred Fish, 3-Jan-86.
  6.  */
  7.  
  8. /* !!! To those who haven't figured it out yet:
  9.  * !!! set stack to 15000 before compiling.
  10.  * !!! This is a generally good thing to do if
  11.  * !!! the compiler blows up on a large source.
  12.  * !!! if your program suddenly KILLS the compiler,
  13.  * !!! increase stack by 5K and try again. jeeze you guys.
  14.  */
  15. /* This program was written to show the use of gadgets in a
  16.  * window. Thus one menu, one auto requester, but lots of
  17.  * gadget types.
  18.  * For the sake of example, two mutual exclude gadgets
  19.  * (female/male) are shown that perform a function that might
  20.  * be better implemented as a toggle image, in a manner similar
  21.  * to that shown in the inflection Mode gadget.
  22.  * Again for the sake of example, the proportional gadgets
  23.  * are generated dynamicly (that is, copied from a template and
  24.  * filled in), whereas most gadgets are declared staticly in
  25.  * the struct declaration, which saves the initialization code
  26.  * space.
  27.  * Lastly, for the sake of example, this program is extremely
  28.  * verbose in the way of comments. Hope you don't mind.
  29.  */
  30. /* Written by David M Lucas. */
  31. /* If you find somthing you don't like, fix it! Have fun! */
  32. /* Send complaints to /dev/null. really. */
  33. /* Thanks Amiga. */
  34.  
  35. #include "exec/types.h"
  36. #include "exec/exec.h"
  37. #include "intuition/intuition.h"
  38. #include "intuition/intuitionbase.h"
  39. #include "graphics/regions.h"
  40. #include "graphics/copper.h"
  41. #include "graphics/gels.h"
  42. #include "graphics/gfxbase.h"
  43. #include "devices/keymap.h"
  44. #include "hardware/blit.h"
  45. #include "devices/narrator.h"
  46. #include "libraries/translator.h"
  47.  
  48. #ifndef LIBRARY_VERSION
  49. #  define LIBRARY_VERSION (1)
  50. #endif
  51.  
  52. /* #define DEBUG */
  53.  
  54. #define CONTWINDW 321 /* Overall Control Window Width/Height */
  55. #define CONTWINDH 123
  56. #define FACEWINDW 32  /* Overall Face Window Width / Height */
  57. #define FACEWINDH 44  /* this includes borders, incedently */
  58.  
  59. /* Pen numbers to draw gadget borders/images/text with */
  60. #define REDP   3        /* color in register 3 once was red */
  61. #define BLKP   2        /* color in register 2 was black */
  62. #define WHTP   1        /* color in register 1 was white */
  63. #define BLUP   0        /* color in register 0 was blue */
  64.  
  65. /* the length of the English and phonetic buffers */
  66. #define ESTRINGSIZE 512
  67. #define PSTRINGSIZE 768 /* phonemes are longer than english */
  68.  
  69. #define NUMPROPS 4      /* number of proportional gadgets */
  70.  
  71. /* Ranges of proportional data */
  72. #define RNGFREQ  (MAXFREQ  - MINFREQ)  +1
  73. #define RNGRATE  (MAXRATE  - MINRATE)  +1
  74. #define RNGPITCH (MAXPITCH - MINPITCH) +1
  75. #define RNGVOL   (MAXVOL   - MINVOL)   +1
  76.  
  77. struct TextAttr TestFont = /* Needed for opening screen */
  78.    {
  79.    (STRPTR)"topaz.font",
  80.    TOPAZ_EIGHTY, 0, 0
  81.    };
  82.  
  83. /* Which audio channels to use */
  84. BYTE audio_chan[] = {3, 5, 10, 12};
  85. /* Pointer to translator library vectors */
  86. struct Library *TranslatorBase = 0;
  87. struct MsgPort talk_port; /* Message port for the say's I/O  */
  88. struct MsgPort read_port; /* Message port for the say's I/O  */
  89. struct mouth_rb mouth_io;  /* IO Request block, mouth flavor */
  90. /* IO Request block, narrator flavor */
  91. struct narrator_rb voice_io;
  92. /* indicative of the Open return */
  93. UBYTE NarratorOpenError = -1;           /* not yet opened */
  94. /* indicative of a Translations success */
  95. UBYTE TranslatorError = 0;
  96. USHORT i;
  97.  
  98. /* These are used to draw the eyes and mouth size relative */
  99. USHORT MouthWMult;
  100. USHORT EyesLeft;
  101. USHORT MouthHMult;
  102. USHORT EyesTop;
  103. USHORT EyesBottom;
  104. USHORT YMouthCenter;  /* Pixels from top edge */
  105. USHORT XMouthCenter;  /* Pixels from left edge */
  106. USHORT yaw;
  107. USHORT LipWidth, LipHeight;
  108.  
  109. /* String Gadgets *********************************************
  110.  * First the string gadgets.
  111.  * 1) because the Phonetic string is refreshed programaticly
  112.  * (that is, deleted and added again) quite often, and doing
  113.  * this requires the use of RefreshGadgets(), and this causes
  114.  * gadgets that are closer to the beginning of the list than
  115.  * the gadget given to RefreshGadgets() to flicker.
  116.  * 2) because they don't flicker when OTHER gadgets
  117.  * (ie female/male, coming up) are deleted and added.
  118.  */
  119. /* These'll be used to put a nice double line border around
  120.  * each of the two string gadgets.
  121.  */
  122. /* y,x pairs drawn as a connected line. Be sure to have an even
  123.  * number of arguments (ie complete pairs).
  124.  */
  125.  
  126. USHORT StrVectors[] = {
  127.    0, 0,   297, 0,   297, 14,   0, 14,
  128.    0, 1,   296, 1,   296, 13,   1, 13,
  129.    1, 1
  130. };
  131. struct Border StrBorder = {
  132.    -4, -3,           /* initial offsets, gadget relative */
  133.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  134.    9,                /* number of vectors */
  135.    StrVectors,     /* pointer to the actual array of vectors */
  136.    NULL       /* no next Border, can point to another border */
  137. };
  138.  
  139. /* The same undo buffer is used for both string gadgets,
  140.  * this is sized to largest so that largest fits.
  141.  */
  142. UBYTE UndoBuffer[PSTRINGSIZE];
  143.  
  144. /* English String Gadget is where the user types in English */
  145. /* default text */
  146. UBYTE EnglBuffer[ESTRINGSIZE] = "This is amiga speaking.";
  147. struct StringInfo EnglInfo = {
  148.    EnglBuffer,    /* pointer to I/O buffer */
  149.    UndoBuffer,    /* pointer to undo buffer */
  150.    0,             /* buffer position */
  151.    ESTRINGSIZE,   /* max number of chars, including NULL */
  152.    0, 0,          /* first char in display, undo positions */
  153.    24,          /* number of chars (currently) in the buffer */
  154.    0, 0, 0,    /* position variables calculated by Intuition */
  155.    NULL,          /* no pointer to RastPort */
  156.    0,             /* not a LongInt string gadget */
  157.    NULL           /* no pointer to alternate keymap */
  158. };
  159. struct IntuiText EnglText = {
  160.    WHTP, BLUP,    /* FrontPen, BackPen */
  161.    JAM1,          /* DrawMode */
  162.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  163.    &TestFont,     /* pointer to TextFont */
  164.    "English:",    /* pointer to Text */
  165.    NULL           /* no pointer to NextText */
  166. };
  167. struct Gadget EnglStrGadget = {
  168.    NULL,             /* pointer to Next Gadget */
  169.    11, 63, 290, 10,  /* (Left Top Width Height) Hit Box */
  170.    GADGHCOMP,        /* Flags */
  171.    RELVERIFY,        /* Activation flags */
  172.    STRGADGET,        /* Type */
  173.    (APTR)&StrBorder, /* pointer to Border Image */
  174.    NULL,             /* no pointer to SelectRender */
  175.    &EnglText,        /* pointer to GadgetText */
  176.    0,                /* no MutualExclude */
  177.    (APTR)&EnglInfo,  /* pointer to SpecialInfo */
  178.    0,                /* no ID */
  179.    NULL              /* no pointer to special data */
  180. };
  181.  
  182. /* Phonetic string gadget is where the program puts the
  183.  * translated string, necessating a call to RefreshGadgets(),
  184.  * and is where the user can type in Phonemes.
  185.  */
  186. UBYTE PhonBuffer[PSTRINGSIZE] =
  187.   "DHIHS IHZ AHMIY3GAH SPIY4KIHNX.";
  188. struct StringInfo PhonInfo = {
  189.    PhonBuffer,    /* pointer to input buffer */
  190.    UndoBuffer,    /* pointer to undo buffer */
  191.    0,             /* initial buffer position */
  192.    PSTRINGSIZE,   /* max number of chars, including NULL */
  193.    0, 0,          /* display, undo positions */
  194.    32,          /* number of chars (currently) in the buffer */
  195.    0, 0, 0,    /* position variables calculated by Intuition */
  196.    NULL,          /* no pointer to RastPort */
  197.    NULL,          /* not a LongInt string gadget */
  198.    NULL           /* no pointer to alternate keymap */
  199. };
  200. struct IntuiText PhonText = {
  201.    WHTP, BLUP,    /* FrontPen, BackPen */
  202.    JAM1,          /* DrawMode */
  203.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  204.    &TestFont,     /* pointer to TextFont */
  205.    "Phonetics:",  /* pointer to Text */
  206.    NULL           /* no pointer to NextText */
  207. };
  208. struct Gadget PhonStrGadget = {
  209.    &EnglStrGadget,   /* pointer to Next Gadget */
  210.    11, 94, 290, 10,  /* (Left Top Width Height) Hit Box */
  211.    GADGHCOMP,        /* Flags */
  212.    RELVERIFY,        /* Activation flags */
  213.    STRGADGET,        /* Type */
  214.    (APTR)&StrBorder, /* pointer to Border Image */
  215.    NULL,             /* no pointer to SelectRender */
  216.    &PhonText,        /* pointer to GadgetText */
  217.    0,                /* no MutualExclude */
  218.    (APTR)&PhonInfo,  /* pointer to SpecialInfo */
  219.    0,                /* no ID */
  220.    NULL              /* no pointer to special data */
  221. };
  222.  
  223. /* Now come the Boolean Gadgets.
  224.  * The female/male pair shows the simplest implementation I
  225.  * could think of to show how you can do mutual-exclude type
  226.  * things yourself. They are two toggle gadgets that use
  227.  * highlight image. The program starts with one selected, and
  228.  * then if either of them are hit, both toggle. Gadgets must
  229.  * be deleted and added whenever you want to change structure
  230.  * member values that intuition expects to be coming from the
  231.  * user, not a program (like the SELECTED bit in flags). Note
  232.  * that certain structure values CAN be changed programaticly
  233.  * without all this broohaha. Haha. Consult the intuition
  234.  * manual.
  235.  */
  236. /* Female Toggle (Highlight Image)
  237.    (Quasi mutual exclude with Male Toggle) */
  238. struct Image FemaleImage = {
  239.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  240.    20, 10, 1,  /* Width, Height, Depth */
  241.    NULL,       /* pointer to ImageData */
  242.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  243. };
  244. struct Gadget FemaleGadget = {
  245.    &PhonStrGadget,      /* pointer to Next Gadget */
  246.    134, 34, 20, 10,     /* (Left Top Width Height) Hit Box */
  247.    GADGIMAGE | GADGHCOMP,  /* Flags */
  248.    /* Activation flags */
  249.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  250.    BOOLGADGET,          /* Type */
  251.    (APTR)&FemaleImage,  /* pointer to GadgetRender */
  252.    NULL,                /* no pointer to SelectRender */
  253.    NULL,                /* no pointer to GadgetText */
  254.    0,                   /* no MutualExclude */
  255.    NULL,                /* no pointer to SpecialInfo */
  256.    0,                   /* no ID */
  257.    NULL                 /* no pointer to special data */
  258. };
  259.  
  260. /* Male Toggle (Highlight Image)
  261.    (Quasi mutual Exclude with above) */
  262. struct Image MaleImage = {
  263.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  264.    20, 10, 1,  /* Width, Height, Depth */
  265.    NULL,       /* pointer to ImageData */
  266.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  267. };
  268. struct Gadget MaleGadget = {
  269.    &FemaleGadget,    /* pointer to Next Gadget */
  270.    154, 34, 20, 10,  /* (Left Top Width Height) Hit Box */
  271.    GADGIMAGE | GADGHCOMP | SELECTED,   /* Flags */
  272.    /* Activation flags */
  273.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT | ACTIVATE,
  274.    BOOLGADGET,       /* Type */
  275.    (APTR)&MaleImage, /* pointer to GadgetRender */
  276.    NULL,             /* no pointer to SelectRender */
  277.    NULL,             /* no pointer to GadgetText */
  278.    0,                /* no MutualExclude */
  279.    NULL,             /* no pointer to SpecialInfo */
  280.    0,                /* no ID */
  281.    NULL              /* no pointer to special data */
  282. };
  283.  
  284. /* This boolean toggle gadget has an
  285.  * alternate image that indicates
  286.  * selection. The image stays flipped
  287.  * until it gets another hit. (it toggles)
  288.  */
  289. /* Inflection Mode Toggle (AltImage) *************************/
  290. struct Image HumanImage = {
  291.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  292.    40, 20, 1,  /* Width, Height, Depth */
  293.    NULL,       /* pointer to ImageData */
  294.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  295. };
  296. struct Image RobotImage = {
  297.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  298.    40, 20, 1,  /* Width, Height, Depth */
  299.    NULL,       /* pointer to ImageData */
  300.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  301. };
  302. struct Gadget ModeGadget = {
  303.    &MaleGadget,            /* pointer to Next Gadget */
  304.    134, 2, 40, 20,        /* (Left Top Width Height) Hit Box */
  305.    GADGIMAGE | GADGHIMAGE, /* Flags */
  306.    /* Activation flags */
  307.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  308.    BOOLGADGET,             /* Type */
  309.    (APTR)&HumanImage,      /* pointer to GadgetRender */
  310.    (APTR)&RobotImage,      /* pointer to SelectRender */
  311.    NULL,                   /* no pointer to GadgetText */
  312.    0,                      /* no MutualExclude */
  313.    NULL,                   /* no pointer to SpecialInfo */
  314.    0,                      /* no ID */
  315.    NULL                    /* no pointer to special data */
  316. };
  317.  
  318. /* Face Toggle (image and text) ******************************/
  319. struct IntuiText FaceIText = {
  320.    WHTP, BLUP, /* FrontPen, BackPen */
  321.    JAM2,       /* DrawMode */
  322.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  323.    &TestFont,  /* pointer to TextFont */
  324.    "Face",/* pointer to Text */
  325.    NULL        /* no pointer to NextText */
  326. };
  327. struct Image FaceImage = {
  328.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  329.    40, 10, 1,  /* Width, Height, Depth */
  330.    NULL,       /* pointer to ImageData */
  331.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  332. };
  333. struct Gadget FaceGadget = {
  334.    &ModeGadget,            /* pointer to Next Gadget */
  335.    134, 23, 40, 10,       /* (Left Top Width Height) Hit Box */
  336.    GADGIMAGE | GADGHCOMP,  /* Flags */
  337.    /* Activation flags */
  338.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  339.    BOOLGADGET,             /* Type */
  340.    (APTR) &FaceImage,      /* pointer to GadgetRender */
  341.    NULL,                   /* no pointer to SelectRender */
  342.    &FaceIText,             /* pointer to GadgetText */
  343.    0,                      /* no MutualExclude */
  344.    NULL,                   /* no pointer to SpecialInfo */
  345.    0,                      /* no ID */
  346.    NULL                    /* no pointer to special data */
  347. };
  348.  
  349. /* Stop Hit (image and text) ******************************/
  350. struct IntuiText StopIText = {
  351.    WHTP, BLUP, /* FrontPen, BackPen */
  352.    JAM2,       /* DrawMode */
  353.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  354.    &TestFont,  /* pointer to TextFont */
  355.    "Stop",/* pointer to Text */
  356.    NULL        /* no pointer to NextText */
  357. };
  358. struct Image StopImage = {
  359.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  360.    40, 10, 1,  /* Width, Height, Depth */
  361.    NULL,       /* pointer to ImageData */
  362.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  363. };
  364. struct Gadget StopGadget = {
  365.    &FaceGadget,            /* pointer to Next Gadget */
  366.    134, 45, 40, 10,        /* Left Top Width Height Hit Box */
  367.    GADGIMAGE | GADGHCOMP,  /* Flags */
  368.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  369.    BOOLGADGET,             /* Type */
  370.    (APTR) &StopImage,      /* pointer to GadgetRender */
  371.    NULL,                   /* no pointer to SelectRender */
  372.    &StopIText,             /* pointer to GadgetText */
  373.    0,                      /* no MutualExclude */
  374.    NULL,                   /* no pointer to SpecialInfo */
  375.    0,                      /* no ID */
  376.    NULL                    /* no pointer to special data */
  377. };
  378.  
  379. /* This is a hit (as opposed to toggle)
  380.    gadget that starts the translation.*/
  381. /* Translate Hit (Highlight image) ***************************/
  382. USHORT TransVectors[] = {
  383.    0, 0,    79, 0,    79, 13,   0, 13,
  384.    0, 1,    78, 1,    78, 12,   1, 12,
  385.    1, 1
  386. };
  387. struct Border TransBorder = {
  388.    -4, -3,           /* initial offsets, gadget relative */
  389.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  390.    9,                /* number of vectors */
  391.    TransVectors,     /* pointer to the array of vectors */
  392.    NULL              /* no next Border, can point to another */
  393. };
  394. struct IntuiText TranslateIText = {
  395.    WHTP, BLUP, /* FrontPen, BackPen */
  396.    JAM2,       /* DrawMode */
  397.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  398.    &TestFont,  /* pointer to TextFont */
  399.    "Translate",/* pointer to Text */
  400.    NULL        /* no pointer to NextText */
  401. };
  402. struct Gadget TranslateGadget = {
  403.    &StopGadget,      /* pointer to Next Gadget */
  404.    229, 48, 71, 8,   /* (Left Top Width Height) Hit Box */
  405.    GADGHCOMP,        /* Flags */
  406.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  407.    BOOLGADGET,       /* Type */
  408.    (APTR)&TransBorder,  /* no pointer to GadgetRender */
  409.    NULL,             /* no pointer to SelectRender */
  410.    &TranslateIText,  /* pointer to GadgetText */
  411.    0,                /* no MutualExclude */
  412.    NULL,             /* no pointer to SpecialInfo */
  413.    0,                /* no ID */
  414.    NULL              /* no pointer to special data */
  415. };
  416.  
  417. /* This is a hit (as opposed to toggle) Starts the narration */
  418. /* Speak Hit (Highlight Image) *******************************/
  419. USHORT SpeakVectors[] = {
  420.    0, 0,    47, 0,    47, 13,   0, 13,
  421.    0, 1,    46, 1,    46, 12,   1, 12,
  422.    1, 1
  423. };
  424. struct Border SpeakBorder = {
  425.    -4, -3,           /* initial offsets, gadget relative */
  426.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  427.    9,                /* number of vectors */
  428.    SpeakVectors,   /* pointer to the actual array of vectors */
  429.    NULL       /* no next Border, can point to another border */
  430. };
  431. struct IntuiText SpeakIText = {
  432.    WHTP, BLUP, /* FrontPen, BackPen */
  433.    JAM2,       /* DrawMode */
  434.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  435.    &TestFont,  /* pointer to TextFont */
  436.    "Speak",    /* pointer to Text */
  437.    NULL        /* no pointer to NextText */
  438. };
  439. struct Gadget SpeakGadget = {
  440.    &TranslateGadget, /* pointer to Next Gadget */
  441.    261, 79, 40, 8,   /* (Left Top Width Height) Hit Box */
  442.    GADGHCOMP,        /* Flags */
  443.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  444.    BOOLGADGET,       /* Type */
  445.    (APTR)&SpeakBorder,  /* pointer to GadgetRender */
  446.    NULL,             /* no pointer to SelectRender */
  447.    &SpeakIText,      /* pointer to GadgetText */
  448.    0,                /* no MutualExclude */
  449.    NULL,             /* no pointer to SpecialInfo */
  450.    0,                /* no ID */
  451.    NULL              /* no pointer to special data */
  452. };
  453.  
  454. /* Now the proportional gadgets. */
  455. /* Proportional Gadgets **************************************/
  456. /* The following variables are used to create proportional
  457.  * Gadgets. These variables will be filled in with copies of
  458.  * the generic Gadgetry below.
  459.  */
  460. SHORT PropCount = 0;       /* index to next available Gadget */
  461. struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */
  462. /* dummy AUTOKNOB Images are required */
  463. struct Image PImages[NUMPROPS];
  464. /* These get copies of TPropInfo */
  465. struct PropInfo PInfos[NUMPROPS];
  466. /* These get copies of TPropGadget */
  467. struct Gadget Props[NUMPROPS];
  468. struct IntuiText TPropText = {
  469.    WHTP, BLUP,   /* FrontPen, BackPen */
  470.    JAM1,         /* DrawMode */
  471.    0, -10,       /* LeftEdge, TopEdge (relative to gadget) */
  472.    &TestFont,    /* pointer to TextFont */
  473.    NULL,         /* pointer to Text is filled at runtime */
  474.    NULL          /* no pointer to NextText */
  475. };   
  476. struct PropInfo TPropInfo = {
  477.    AUTOKNOB | FREEHORIZ,  /* Flags */
  478.    0, 0,            /* Pots:  Horiz, Vert: both start at 0 */
  479.    0x1FFF, 0x1FFF,  /* Bodies: Horiz is 1/8, Vert is 1/8 */
  480.    0, 0, 0, 0, 0, 0 /* System usage stuff */
  481. };
  482. /* this is the template for the Gadget of a horizontal */
  483. /* Proportional Gadget */
  484. struct Gadget TPropGadget = {
  485.    &SpeakGadget,              /* pointer to NextGadget */
  486.    7, 12, 115, 10,            /* Select Box L T W H */
  487.    GADGHCOMP | GADGIMAGE,     /* Flags */
  488.    GADGIMMEDIATE | RELVERIFY, /* Activation flags */
  489.    PROPGADGET,                /* Type */
  490.    NULL,       /* pointer to Image filled in later */
  491.    NULL,       /* no pointer to SelectRender */
  492.    NULL,       /* no pointer to GadgetText */
  493.    0,          /* no MutualExclude */
  494.    NULL,       /* SpecialInfo proportional data filled later */
  495.    0,          /* no ID */
  496.    NULL        /* no pointer to special data */
  497. };
  498.  
  499. struct IntuitionBase *IntuitionBase = 0;
  500. struct GfxBase *GfxBase = 0;
  501.  
  502. /* Only one menu. */
  503.  
  504. ULONG MenuNumber;
  505. ULONG TheMenu;
  506. ULONG TheItem;
  507.  
  508. struct IntuiText MenuItemText = {
  509.    BLUP,         /* Front Pen */
  510.    WHTP,         /* Back pen */
  511.    JAM2,         /* Draw Mode */
  512.    0,            /* Left Edge */
  513.    0,            /* Top */
  514.    &TestFont,    /* pointer to TextFont */
  515.    "About SpeechToy...", /* text */
  516.    NULL          /* next */
  517. };
  518. struct MenuItem MyMenuItem = {
  519.    NULL,                /* pointer to next item */
  520.    0,                   /* left */
  521.    0,                   /* top */
  522.    150,                 /* width */
  523.    8,                   /* height */
  524.    ITEMTEXT | ITEMENABLED | HIGHCOMP,  /* flags */
  525.    0,                   /* no mutual exclude */
  526.    (APTR)&MenuItemText, /* Render */
  527.    NULL,                /* pointer to alternate image */
  528.    NULL,                /* Command "amiga" char */
  529.    NULL,                /* Sub Item */
  530.    MENUNULL             /* nextselect */
  531. };
  532.  
  533. struct Menu MyMenu = {
  534.    NULL,          /* pointer to next menu */
  535.    0,0,150,0,     /* left,0,Width,0 */
  536.    MENUENABLED,   /* flags */
  537.    "SpeachToy Menu",   /* menu name */
  538.    &MyMenuItem    /* First Item in list */
  539. };
  540.  
  541. struct IntuiText ReqText1 = {
  542.    BLUP,         /* Front Pen */
  543.    WHTP,         /* Back pen */
  544.    JAM2,         /* Draw Mode */
  545.    5,            /* Left Edge */
  546.    23,           /* Top */
  547.    &TestFont,    /* pointer to TextFont */
  548.    "Version 1.1  21 Dec, 1985",  /* text */
  549.    NULL          /* next */
  550. };
  551. struct IntuiText ReqText2 = {
  552.    BLUP,         /* Front Pen */
  553.    WHTP,         /* Back pen */
  554.    JAM2,         /* Draw Mode */
  555.    5,            /* Left Edge */
  556.    13,           /* Top */
  557.    &TestFont,    /* pointer to TextFont */
  558.    "Freeware - Public Domain ", /* text */
  559.    &ReqText1     /* next */
  560. };
  561. struct IntuiText ReqText3 = {
  562.    BLUP,         /* Front Pen */
  563.    WHTP,         /* Back pen */
  564.    JAM2,         /* Draw Mode */
  565.    5,            /* Left Edge */
  566.    3,            /* Top */
  567.    &TestFont,    /* pointer to TextFont */
  568.    "Written by David M Lucas ", /* text */
  569.    &ReqText2     /* next */
  570. };
  571.  
  572. struct IntuiText OKIText = {
  573.    BLUP, WHTP, /* FrontPen, BackPen */
  574.    JAM2,       /* DrawMode */
  575.    6, 3,       /* LeftEdge, TopEdge (relative to gadget) */
  576.    &TestFont,  /* pointer to TextFont */
  577.    "OK",       /* pointer to Text */
  578.    NULL        /* no pointer to NextText */
  579. };
  580.  
  581. struct Requester *AboutRequester;
  582.  
  583. USHORT autoret;
  584. struct Window *ControlWindow = NULL;
  585. struct Window *FaceWindow = NULL;
  586. struct IntuiMessage *MyIntuiMessage;
  587. struct NewWindow NewControlWindow = {
  588.    00, 11,                    /* start LeftEdge, TopEdge */
  589.    CONTWINDW, CONTWINDH,      /* start Width, Height */
  590.    -1, -1,                    /* DetailPen, BlockPen */
  591.    GADGETUP | CLOSEWINDOW | MENUPICK,  /* IDCMP FLAGS */
  592.    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
  593.    | GIMMEZEROZERO | ACTIVATE,/* Flags (can be NULL) */
  594.    &Props[NUMPROPS-1],        /* Pointer to FirstGadget */
  595.    NULL,                    /* no pointer to first CheckMark */
  596.    "SpeechToy",               /* Title (can be NULL) */
  597.    NULL,                      /* no Pointer to Screen */
  598.    NULL,                      /* no Pointer to BitMap */
  599.    20, 20,                    /* Min/max  Sizable to (w/h) */
  600.    CONTWINDW, CONTWINDH,      /* These aint used, can't size */
  601.    WBENCHSCREEN         /* Type of screen window appears in */
  602. };
  603.  
  604. struct NewWindow NewFaceWindow = {
  605.    CONTWINDW, 11,             /* start LeftEdge, TopEdge */
  606.    FACEWINDW * 2, FACEWINDH,  /* start Width, Height */
  607.    -1, -1,                    /* DetailPen, BlockPen */
  608.    SIZEVERIFY | NEWSIZE | MENUPICK,      /* IDCMP FLAGS */
  609.    /* Flags (can be NULL) */
  610.    WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING
  611.     | SIZEBBOTTOM | GIMMEZEROZERO | ACTIVATE,
  612.    NULL,                /* no Pointer to FirstGadget */
  613.    NULL,                /* no Pointer to first CheckMark */
  614.    "Face",              /* Title */
  615.    NULL,                /* no Pointer to Screen */
  616.    NULL,                /* no Pointer to BitMap */
  617.    FACEWINDW, FACEWINDH,/* Minimum sizeable to */
  618.    640, 200,            /* Maximum sizeable to */
  619.    WBENCHSCREEN         /* Type of screen window appears in */
  620. };
  621.  
  622. USHORT FemaleIData[] = {
  623. /*   ----    -  These nibbles matter to image. */
  624.    0x0000, 0x0000,
  625.    0x00F0, 0x0000,
  626.    0x0198, 0x0000,
  627.    0x030C, 0x0000,
  628.    0x0198, 0x0000,
  629.    0x00F0, 0x0000,
  630.    0x0060, 0x0000,
  631.    0x01F8, 0x0000,
  632.    0x0060, 0x0000,
  633.    0x0000, 0x0000
  634. };
  635.  
  636. USHORT MaleIData[] = {
  637. /*   ----    -   These nibbles matter to image. */
  638.    0x0000, 0x0000,
  639.    0x003E, 0x0000,
  640.    0x000E, 0x0000,
  641.    0x0036, 0x0000,
  642.    0x01E0, 0x0000,
  643.    0x0330, 0x0000,
  644.    0x0618, 0x0000,
  645.    0x0330, 0x0000,
  646.    0x01E0, 0x0000,
  647.    0x0000, 0x0000
  648. };
  649. USHORT HumanIData[] = {
  650. /*   ----   ----   --   These nibbles matter to image. */
  651.    0x0000,0x0000,0x0000,
  652.    0x0000,0x0000,0x0000,
  653.    0x0000,0x0000,0x0000,
  654.    0x0000,0x0000,0x0000,
  655.    0x0007,0x9E00,0x0000,
  656.    0x0001,0x8600,0x0000,
  657.    0x0000,0x0000,0x0000,
  658.    0x0000,0x0000,0x0000,
  659.    0x0000,0x2000,0x0000,
  660.    0x0000,0x1000,0x0000,
  661.    0x0000,0x0800,0x0000,
  662.    0x0000,0x7C00,0x0000,
  663.    0x0000,0x0000,0x0000,
  664.    0x0000,0x0000,0x0000,
  665.    0x0000,0x0000,0x0000,
  666.    0x0000,0x7800,0x0000,
  667.    0x0000,0x0000,0x0000,
  668.    0x0000,0x0000,0x0000,
  669.    0x0000,0x0000,0x0000,
  670.    0x0000,0x0000,0x0000
  671. };
  672. USHORT RobotIData[] = {
  673. /*   ----   ----   --   These nibbles matter to image. */
  674.    0x0000,0x0000,0x0000,
  675.    0x0000,0x0000,0x0000,
  676.    0x0000,0x0000,0x0000,
  677.    0x0000,0x0000,0x0000,
  678.    0x0007,0x9E00,0x0000,
  679.    0x0004,0x9200,0x0000,
  680.    0x0007,0x9E00,0x0000,
  681.    0x0000,0x0000,0x0000,
  682.    0x0000,0x0000,0x0000,
  683.    0x0000,0x0000,0x0000,
  684.    0x0000,0x0000,0x0000,
  685.    0x0000,0x0000,0x0000,
  686.    0x0000,0x0000,0x0000,
  687.    0x0001,0xF800,0x0000,
  688.    0x0001,0x0800,0x0000,
  689.    0x0001,0xF800,0x0000,
  690.    0x0000,0x0000,0x0000,
  691.    0x0000,0x0000,0x0000,
  692.    0x0000,0x0000,0x0000,
  693.    0x0000,0x0000,0x0000
  694. };
  695. USHORT FaceIData[] = {
  696. /*   ----   ----   --   These nibbles matter to image. */
  697.    0x0000,0x0000,0x0000,
  698.    0x0000,0x0000,0x0000,
  699.    0x0000,0x0000,0x0000,
  700.    0x0000,0x0000,0x0000,
  701.    0x0000,0x0000,0x0000,
  702.    0x0000,0x0000,0x0000,
  703.    0x0000,0x0000,0x0000,
  704.    0x0000,0x0000,0x0000,
  705.    0x0000,0x0000,0x0000,
  706.    0x0000,0x0000,0x0000
  707. };
  708. USHORT StopIData[] = {
  709. /*   ----   ----   --   These nibbles matter to image. */
  710.    0x0000,0x0000,0x0000,
  711.    0x0000,0x0000,0x0000,
  712.    0x0000,0x0000,0x0000,
  713.    0x0000,0x0000,0x0000,
  714.    0x0000,0x0000,0x0000,
  715.    0x0000,0x0000,0x0000,
  716.    0x0000,0x0000,0x0000,
  717.    0x0000,0x0000,0x0000,
  718.    0x0000,0x0000,0x0000,
  719.    0x0000,0x0000,0x0000
  720. };
  721. USHORT *FemaleIData_chip = 0;
  722. USHORT *MaleIData_chip = 0;
  723. USHORT *HumanIData_chip = 0;
  724. USHORT *RobotIData_chip = 0;
  725. USHORT *FaceIData_chip = 0;
  726. USHORT *StopIData_chip = 0;
  727.  
  728. /** start of code ***************************/
  729. main()
  730. {
  731.    ULONG Signals;        /* Wait() tells me which to look at */
  732.    ULONG MIClass;        /* Save quickly, ReplyMsg() asap */
  733.    USHORT MICode;        /* These hold my needed information */
  734.    APTR MIAddress;
  735.  
  736.    /* let MyCleanup know these signals not allocated yet */
  737.    talk_port.mp_SigBit = -1;
  738.    read_port.mp_SigBit = -1;
  739.  
  740.    /* Open those libraries that the program uses directly */
  741.    if ((IntuitionBase = (struct IntuitionBase *)
  742.     OpenLibrary("intuition.library", LIBRARY_VERSION)) == 0) {
  743. #ifdef DEBUG
  744.       printf("Can't open the intuition library\n");
  745. #endif
  746.       MyCleanup();
  747.       exit(FALSE);
  748.    }
  749.  
  750.    if ((GfxBase = (struct GfxBase *)
  751.     OpenLibrary("graphics.library", LIBRARY_VERSION)) == 0) {
  752. #ifdef DEBUG
  753.       printf("Can't open the graphics library\n");
  754. #endif
  755.       MyCleanup();
  756.       exit(FALSE);
  757.    }
  758.  
  759.    if ((TranslatorBase = (struct Library *)
  760.     OpenLibrary("translator.library", LIBRARY_VERSION)) == 0) {
  761. #ifdef DEBUG
  762.       printf("Can't open the translator library\n");
  763. #endif
  764.       MyCleanup();
  765.       exit(FALSE);
  766.    }
  767.  
  768.    /* Open the device */
  769.    if ((NarratorOpenError = OpenDevice("narrator.device", 0,
  770.     &voice_io, 0)) != 0) {
  771. #ifdef DEBUG
  772.       printf("Can't open the narrator device\n");
  773. #endif
  774.       MyCleanup();
  775.       exit(FALSE);
  776.    }
  777.    /* This is where the proportional gadgets are set up, using
  778.     * the templates that were declared staticly.
  779.     */
  780.    for(PropCount = 0; PropCount < NUMPROPS; PropCount++) {
  781.       PTexts[PropCount] = TPropText;
  782.       Props[PropCount] = TPropGadget;
  783.       PInfos[PropCount] = TPropInfo;
  784.       Props[PropCount].GadgetText = (struct IntuiText *)
  785.        &PTexts[PropCount];
  786.       Props[PropCount].GadgetRender = (APTR)
  787.        &PImages[PropCount];
  788.       Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount];
  789.       switch (PropCount) {
  790.       case 0:
  791.          PTexts[PropCount].IText = "Sample Freq:";
  792.          if (DEFFREQ == MAXFREQ)
  793.             PInfos[PropCount].HorizPot = 65535;
  794.          else
  795.             PInfos[PropCount].HorizPot = ((DEFFREQ - MINFREQ)
  796.              << 16) / (MAXFREQ - MINFREQ);
  797.          break;
  798.       case 1:
  799.          PTexts[PropCount].IText = "Rate:";
  800.          Props[PropCount].TopEdge += 22;
  801.          Props[PropCount].NextGadget = &Props[PropCount-1];
  802.          if (DEFRATE == MAXRATE)
  803.             PInfos[PropCount].HorizPot = 65535;
  804.          else
  805.             PInfos[PropCount].HorizPot = ((DEFRATE - MINRATE)
  806.              << 16) / (MAXRATE - MINRATE);
  807.          break;
  808.       case 2:
  809.          PTexts[PropCount].IText = "Pitch:";
  810.          Props[PropCount].LeftEdge += 183;
  811.          Props[PropCount].NextGadget = &Props[PropCount-1];
  812.          if (DEFPITCH == MAXPITCH)
  813.             PInfos[PropCount].HorizPot = 65535;
  814.          else
  815.             PInfos[PropCount].HorizPot = ((DEFPITCH-MINPITCH)
  816.              << 16) / (MAXPITCH - MINPITCH);
  817.          break;
  818.       case 3:
  819.          PTexts[PropCount].IText = "Volume:";
  820.          Props[PropCount].TopEdge += 22;
  821.          Props[PropCount].LeftEdge += 183;
  822.          Props[PropCount].NextGadget = &Props[PropCount-1];
  823.          if (DEFVOL == MAXVOL)
  824.             PInfos[PropCount].HorizPot = 65535;
  825.          else
  826.             PInfos[PropCount].HorizPot = ((DEFVOL - MINVOL)
  827.              << 16) / (MAXVOL - MINVOL);
  828.          break;
  829.       }
  830.    }
  831.  
  832.    /* Now allocate memory accessable by the chips for images */
  833.    if (InitImages() != TRUE) {
  834. #ifdef DEBUG
  835.       printf("Couldn't Allocate Images in chip memory.\n");
  836. #endif
  837.       MyCleanup();
  838.       exit(FALSE);
  839.    }
  840.  
  841.    /* Set up the write port, allocate the signal, */
  842.    /* and the message */
  843.    talk_port.mp_Node.ln_Type = NT_MSGPORT;
  844.    talk_port.mp_Flags = 0;
  845.    if ((talk_port.mp_SigBit = AllocSignal(-1)) == -1) {
  846. #ifdef DEBUG
  847.       printf("Couldn't Allocate talk Signal bit\n");
  848. #endif
  849.       MyCleanup();
  850.       exit(FALSE);
  851.    }
  852.    talk_port.mp_SigTask = (struct Task *) FindTask((char *)
  853.     NULL);
  854.    NewList(&talk_port.mp_MsgList);
  855.  
  856.    /* Set up the read port, allocate the signal, */
  857.    /*  and the message */
  858.    read_port.mp_Node.ln_Type = NT_MSGPORT;
  859.    read_port.mp_Flags = 0;
  860.    if ((read_port.mp_SigBit = AllocSignal(-1)) == -1) {
  861. #ifdef DEBUG
  862.       printf("Couldn't Allocate read Signal bit\n");
  863. #endif
  864.       MyCleanup();
  865.       exit(FALSE);
  866.    }
  867.    read_port.mp_SigTask = (struct Task *)
  868.     FindTask((char *) NULL);
  869.    NewList(&read_port.mp_MsgList);
  870.  
  871.    /* Set up the write channel information */
  872.    voice_io.ch_masks = (audio_chan);
  873.    voice_io.nm_masks = sizeof(audio_chan);
  874.    voice_io.mouths = 0;
  875.    voice_io.message.io_Message.mn_ReplyPort = &talk_port;
  876.    voice_io.message.io_Command = CMD_WRITE;
  877.    voice_io.message.io_Offset = 0;
  878.    voice_io.message.io_Data = (APTR)PhonBuffer;
  879.    voice_io.message.io_Message.mn_Length = sizeof(voice_io);
  880.  
  881.   /* Set up the read channel information */
  882.    mouth_io.voice = voice_io;
  883.    mouth_io.width = 0;
  884.    mouth_io.height = 0;
  885.    mouth_io.voice.message.io_Message.mn_ReplyPort = &read_port;
  886.    mouth_io.voice.message.io_Command = CMD_READ;
  887.    mouth_io.voice.message.io_Error = 0;
  888.    if (FaceWindow == NULL) {
  889.       if ((ControlWindow = (struct Window *)OpenWindow
  890.        (&NewControlWindow)) == NULL) {
  891. #ifdef DEBUG
  892.          printf("Couldn't open the control window.\n");
  893. #endif
  894.          MyCleanup();
  895.          exit(FALSE);
  896.       }
  897.    }
  898.  
  899.    /* fill background of window */
  900.    SetAPen(ControlWindow->RPort, BLKP);
  901.    RectFill(ControlWindow->RPort,0,0,
  902.     ControlWindow->GZZWidth, ControlWindow->GZZHeight);
  903.    RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL);
  904.  
  905.    SetMenuStrip(ControlWindow, &MyMenu);
  906.  
  907. /* !!! Ah, But what if FaceWindow's not been opened? */
  908.    for (;;) {  /* ever wait for a signal and process it */
  909.       /* wait lets the rest of the system run, */
  910.       /* this program sleeps */
  911.       Signals = Wait((1 << ControlWindow->UserPort->mp_SigBit)
  912. | (1 << FaceWindow->UserPort->mp_SigBit)
  913. | (1 << voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)
  914. | (1 <<
  915.    mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit));
  916.       /* now check to see to what we owe the intrusion */
  917.  
  918.       if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
  919.          /* Process the Intuition message */
  920.          while (MyIntuiMessage=(struct IntuiMessage *)
  921.                       GetMsg(ControlWindow->UserPort)) {
  922.             /* Get all the needed info and give message back */
  923.             MIClass = MyIntuiMessage->Class;
  924.             MICode = MyIntuiMessage->Code;
  925.             MIAddress = MyIntuiMessage->IAddress;
  926.             ReplyMsg(MyIntuiMessage);
  927.             /* Now, what was it you wanted? */
  928.             switch (MIClass) {
  929.                case MENUPICK:
  930.                   menumessage(MICode, ControlWindow);
  931.                   break;
  932.                case GADGETUP:         /* reply, then process */
  933.                   gadgetmessage(MIAddress, ControlWindow);
  934.                   break;
  935.                case CLOSEWINDOW:       /* bye! */
  936.                   while (MyIntuiMessage = (struct
  937.                    IntuiMessage *) GetMsg(
  938.                    ControlWindow->UserPort))
  939.                     ReplyMsg(MyIntuiMessage);
  940.                   MyCleanup();
  941.                   exit(TRUE);
  942.                   break;
  943.                default:
  944. #ifdef DEBUG
  945.                   printf("Unhandled Message Received.\n");
  946. #endif
  947.                   break;
  948.             }  /* switch */
  949.          } /* while */
  950.       } /* if */
  951.  
  952.  
  953.       /* Woken by intuition for FaceWindow*/
  954.       if (Signals & (1<< FaceWindow->UserPort->mp_SigBit)) {
  955.          /* Process the Intuition message */
  956.          while (MyIntuiMessage=(struct IntuiMessage *)
  957.           GetMsg(FaceWindow->UserPort)) {
  958.             switch (MyIntuiMessage->Class) {
  959.                case SIZEVERIFY:
  960.                   ReplyMsg(MyIntuiMessage);
  961.                   break;
  962.                case MENUPICK:
  963.                   menumessage(MyIntuiMessage->Code,FaceWindow);
  964.                   ReplyMsg(MyIntuiMessage);
  965.                   break;
  966.                case NEWSIZE:  /* Don't reply until processed */
  967.                   DrawFace();
  968.                   ReplyMsg(MyIntuiMessage);
  969.                   break;
  970.                default:
  971. #ifdef DEBUG
  972.                   printf("Unhandled Message Received.\n");
  973. #endif
  974.                   ReplyMsg(MyIntuiMessage);
  975.                   break;
  976.             }  /* switch */
  977.          } /* while */
  978.       } /* if */
  979.  
  980.       /* A voice SendIO (Write) has completed */
  981.       if (Signals & (1 <<
  982.        voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  983.          /* Was it Sucessful? filter out the abort error */
  984.          if (voice_io.message.io_Error == -2)
  985.             voice_io.message.io_Error = 0;
  986.          if (voice_io.message.io_Error != 0) {
  987. #ifdef DEBUG
  988.             printf("Narrator won't. (%ld)\n",
  989.              voice_io.message.io_Error);
  990. #endif
  991.             /* flash this screen */
  992.             DisplayBeep(ControlWindow->WScreen);
  993.             /* let user see where phoneme string was bad. */
  994.             i = RemoveGadget(ControlWindow, &PhonStrGadget);
  995.             /* move the cursor to the error char */
  996.             PhonInfo.BufferPos = voice_io.message.io_Actual -1;
  997.             /* assure cursor (error point) is shown in gad. */
  998.             /* within 29 (number of chars shown) of front */
  999.             if (voice_io.message.io_Actual < 29)
  1000.                PhonInfo.DispPos = 0;
  1001.             /* within 29 of end */
  1002.             else if ((voice_io.message.io_Length -
  1003.                       voice_io.message.io_Actual) < 29)
  1004.                PhonInfo.DispPos = voice_io.message.io_Length
  1005.                                   - 29;
  1006.             else
  1007.                PhonInfo.DispPos = voice_io.message.io_Actual
  1008.                                   - 15;
  1009.             AddGadget(ControlWindow, &PhonStrGadget, i);
  1010.             RefreshGadgets(&PhonStrGadget, ControlWindow,
  1011.              NULL);
  1012.             voice_io.message.io_Error = 0;
  1013.          }
  1014. /*       SpeakGadget.Flags ^= GADGDISABLED;
  1015.          FaceGadget.Flags ^= GADGDISABLED;
  1016. */
  1017.          OnGadget(&SpeakGadget, ControlWindow, NULL);
  1018.          OnGadget(&FaceGadget,  ControlWindow, NULL);
  1019.       }
  1020.  
  1021.       /* A mouth DoIO (Read) has completed */
  1022.       if (Signals & (1 <<
  1023.   mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  1024.          WaitBOVP(&FaceWindow->WScreen->ViewPort);
  1025.          SetAPen(FaceWindow->RPort, WHTP);
  1026.          RectFill(FaceWindow->RPort, 0, EyesBottom,
  1027.           FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1028.          if (MouthWMult == 0)
  1029.             LipWidth = mouth_io.width >> 1;
  1030.          else
  1031.             LipWidth = mouth_io.width * MouthWMult;
  1032.          if (MouthHMult == 0)
  1033.             LipHeight = mouth_io.height >> 1;
  1034.          else
  1035.             LipHeight = mouth_io.height * (MouthHMult);
  1036.          SetAPen(FaceWindow->RPort, REDP);
  1037.          Move(FaceWindow->RPort,
  1038.           XMouthCenter - LipWidth, YMouthCenter);
  1039.          Draw(FaceWindow->RPort,
  1040.           XMouthCenter, YMouthCenter - LipHeight);
  1041.          Draw(FaceWindow->RPort,
  1042.           XMouthCenter + LipWidth, YMouthCenter);
  1043.          Draw(FaceWindow->RPort,
  1044.           XMouthCenter, YMouthCenter + LipHeight);
  1045.          Draw(FaceWindow->RPort,
  1046.           XMouthCenter - LipWidth, YMouthCenter);
  1047.          /* the narrator will give an error when the */
  1048.          /* write has completed and I've tried to read */
  1049.          /* so I stop trying when that happens */
  1050.          if (mouth_io.voice.message.io_Error == 0)
  1051.             SendIO(&mouth_io);
  1052.       }
  1053.    }  /* for */
  1054. }  /* main */
  1055.  
  1056. /* a MENUPICK has been received, this
  1057.  * routine takes the appropriate action
  1058.  */
  1059. menumessage(code, w)
  1060. USHORT code;
  1061. struct Window *w;
  1062. {
  1063.    switch (MENUNUM(code)) {
  1064.       case 0:
  1065.          switch (ITEMNUM(code)) {
  1066.             case 0:
  1067.                AutoRequest(w, &ReqText3, NULL,
  1068.                            &OKIText, 0, 0, 280, 47);
  1069.                break;
  1070.          }
  1071.       break;
  1072.    }
  1073. }
  1074.  
  1075. /* a GADGETUP has been received, this
  1076.  * routine takes the appropriate action
  1077.  */
  1078. gadgetmessage(address, w)
  1079. APTR address;
  1080. struct Window *w;
  1081. {
  1082.    USHORT i;
  1083.    long PropRange;
  1084.    if (address == (APTR)&ModeGadget) {
  1085.       if (ModeGadget.Flags & SELECTED)
  1086.          voice_io.mode = ROBOTICF0;
  1087.       else
  1088.          voice_io.mode = NATURALF0;
  1089.    }
  1090.    else if (address == (APTR)&FaceGadget) {
  1091.       /* tell the write that reads will be forthcomming */
  1092.       if (FaceGadget.Flags & SELECTED) {
  1093.          voice_io.mouths = 1;
  1094.          if ((FaceWindow = (struct Window *)
  1095.           OpenWindow(&NewFaceWindow)) == NULL) {
  1096. #ifdef DEBUG
  1097.             printf("Couldn't open the face window.\n");
  1098. #endif
  1099.             MyCleanup();
  1100.             exit(FALSE);
  1101.          }
  1102.          SetMenuStrip(FaceWindow, &MyMenu);
  1103.          DrawFace();
  1104.       }
  1105.       else { /* FaceGadget de-SELECTed */
  1106.          voice_io.mouths = 0;
  1107.          NewFaceWindow.LeftEdge = FaceWindow->LeftEdge;
  1108.          NewFaceWindow.TopEdge = FaceWindow->TopEdge;
  1109.          NewFaceWindow.Width = FaceWindow->Width;
  1110.          NewFaceWindow.Height = FaceWindow->Height;
  1111.          CloseWindow(FaceWindow);
  1112.          FaceWindow = NULL;
  1113.       }
  1114.    }
  1115.    else if (address == (APTR)&StopGadget) {
  1116.       AbortIO(&voice_io);
  1117.       voice_io.message.io_Error = 0;
  1118.       mouth_io.voice.message.io_Error = 0;
  1119.    }
  1120.    /* Since this program changes a flag that intuition expects
  1121.     * only the user to change (SELECTED bit), this program has
  1122.     * to remove, then change, then add this gadget. Then by
  1123.     * passing the address of this gadget to RefreshGadgets(),
  1124.     * only the gadgets from here to the start of the list will
  1125.     * be refreshed, which minimizes the visible flash that
  1126.     * RefreshGadgets() can introduce.
  1127.     * If one of the two gadgets (female/male) is hit, toggle
  1128.     * the selection of the other gadget (since the gadget hit
  1129.     * was toggled by intuition when it was hit).
  1130.     */
  1131.    else if (address == (APTR)&FemaleGadget) {
  1132.       if (FemaleGadget.Flags & SELECTED)
  1133.       voice_io.sex = FEMALE;
  1134.       else
  1135.       voice_io.sex = MALE;
  1136.       i = RemoveGadget(ControlWindow, &MaleGadget);
  1137.       MaleGadget.Flags ^= SELECTED;
  1138.       AddGadget(ControlWindow, &MaleGadget, i);
  1139.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1140.    }
  1141.    else if (address == (APTR)&MaleGadget) {
  1142.       if (MaleGadget.Flags & SELECTED)
  1143.       voice_io.sex = MALE;
  1144.       else
  1145.       voice_io.sex = FEMALE;
  1146.       i = RemoveGadget(ControlWindow, &FemaleGadget);
  1147.       FemaleGadget.Flags ^= SELECTED;
  1148.       AddGadget(ControlWindow, &FemaleGadget, i);
  1149.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1150.    }
  1151.    /* Since the program changes the contents of the string
  1152.     * gadgets' buffer and it's size, which is something else
  1153.     * intuition doesn't expect a program (as opposed to the
  1154.     * user) to do. The program must remove, then change, then
  1155.     * add this gadget, and then by passing the address of this
  1156.     * gadget to RefreshGadgets(), only the gadgets from here
  1157.     * to the start of the list will be refreshed, which
  1158.     * minimizes the visible flash that RefreshGadgets() can
  1159.     * introduce.
  1160.     */
  1161.    else if (address == (APTR)&TranslateGadget) {
  1162.       i = RemoveGadget(ControlWindow, &PhonStrGadget);
  1163.       if ((TranslatorError = Translate((APTR)EnglBuffer,
  1164.        EnglInfo.NumChars, (APTR)PhonBuffer, PhonInfo.MaxChars))
  1165.        != 0) {
  1166. #ifdef DEBUG
  1167.          printf("Translator won't. (%lx)\n",TranslatorError);
  1168. #endif
  1169.          /* flash this screen */
  1170.          DisplayBeep(ControlWindow->WScreen);
  1171.       }
  1172.       /* Hey! NumChars includes the terminating NULL. */
  1173.       /* This must be done. */
  1174.       PhonInfo.NumChars = voice_io.message.io_Length + 1;
  1175.       if (PhonInfo.DispPos > voice_io.message.io_Length)
  1176.           PhonInfo.DispPos = voice_io.message.io_Length;
  1177.       AddGadget(ControlWindow, &PhonStrGadget, i);
  1178.       RefreshGadgets(&PhonStrGadget, ControlWindow, NULL);
  1179.    }
  1180.    else if (address == (APTR)&SpeakGadget) {
  1181. /*    SpeakGadget.Flags ^= GADGDISABLED;
  1182.       FaceGadget.Flags ^= GADGDISABLED;
  1183. */
  1184.       OffGadget(&SpeakGadget, ControlWindow, NULL);
  1185.       OffGadget(&FaceGadget,  ControlWindow, NULL);
  1186.  
  1187.       voice_io.message.io_Length = strlen(PhonBuffer);
  1188.       SendIO(&voice_io);
  1189.       if (voice_io.mouths == 1) {
  1190.          mouth_io.voice.message.io_Error = 0;
  1191.          SendIO(&mouth_io);
  1192.       }
  1193.    }
  1194.    else if (address == (APTR)&EnglStrGadget);  /* do nothing */
  1195.    else if (address == (APTR)&PhonStrGadget);  /* do nothing */
  1196.    else if (address == (APTR)&Props[0]) {
  1197.       PropRange = RNGFREQ;
  1198.       voice_io.sampfreq = (( (PInfos[0].HorizPot >> 1)
  1199.        * PropRange) >> 15) + MINFREQ;
  1200. #ifdef DEBUG
  1201.       printf("Freq. = %ld\n", voice_io.sampfreq);
  1202. #endif
  1203.    }
  1204.    else if (address == (APTR)&Props[1]) {
  1205.       PropRange = RNGRATE;
  1206.       voice_io.rate = (((PInfos[1].HorizPot >> 1)
  1207.        * PropRange) >> 15) + MINRATE;
  1208. #ifdef DEBUG
  1209.       printf("Rate  = %ld\n", voice_io.rate);
  1210. #endif
  1211.    }
  1212.    else if (address == (APTR)&Props[2]) {
  1213.       PropRange = RNGPITCH;
  1214.       voice_io.pitch = (((PInfos[2].HorizPot >> 1)
  1215.        * PropRange) >> 15) + MINPITCH;
  1216. #ifdef DEBUG
  1217.       printf("Pitch = %ld\n", voice_io.pitch);
  1218. #endif
  1219.    }
  1220.    else if (address == (APTR)&Props[3]) {
  1221.       PropRange = RNGVOL;
  1222.       voice_io.volume = (((PInfos[3].HorizPot >> 1)
  1223.        * PropRange) >> 15) + MINVOL;
  1224. #ifdef DEBUG
  1225.       printf("Vol.  = %ld\n", voice_io.volume);
  1226. #endif
  1227.    }
  1228. #ifdef DEBUG
  1229.    else printf("Unhandled gadget up received!\n");
  1230. #endif
  1231. }
  1232.  
  1233. /* This calculates variables used to draw the mouth
  1234.  * and eyes, as well as redrawing the face.
  1235.  * Proportionality makes it very wierd, but it's
  1236.  * wierder if you don't use a GimmeZeroZero window
  1237.  * and GZZWidth/GZZHeight.
  1238.  */
  1239. DrawFace() {
  1240.    XMouthCenter =  FaceWindow->GZZWidth >> 1;
  1241.    /* set left edge of left eye */
  1242.    EyesLeft = FaceWindow->GZZWidth >> 2;
  1243.    /* multiplier for mouth width */
  1244.    MouthWMult = FaceWindow->GZZWidth >> 6;
  1245.  
  1246.    EyesTop = (FaceWindow->GZZHeight >> 2)
  1247.     - (FaceWindow->GZZHeight >> 4);
  1248.    EyesBottom = EyesTop + (FaceWindow->GZZHeight >> 3) + 1;
  1249.    yaw = FaceWindow->GZZHeight - EyesBottom;
  1250.    YMouthCenter = ((yaw >> 1) + EyesBottom);
  1251.    MouthHMult = yaw >> 5;
  1252.  
  1253.    /* Set pen to White */
  1254.    SetAPen(FaceWindow->RPort, WHTP);
  1255.    RectFill(FaceWindow->RPort, 0, 0,
  1256.     FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1257.  
  1258.    /* Set pen to Blue */
  1259.    SetAPen(FaceWindow->RPort, BLUP);
  1260.    RectFill(FaceWindow->RPort,
  1261.     EyesLeft, EyesTop,
  1262.     EyesLeft + (FaceWindow->GZZWidth >> 3),
  1263.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1264.    RectFill(FaceWindow->RPort,
  1265.     (FaceWindow->GZZWidth >> 1)
  1266.     + (FaceWindow->GZZWidth >> 3),
  1267.     EyesTop,
  1268.     (FaceWindow->GZZWidth >> 1)
  1269.      + (FaceWindow->GZZWidth >> 3) /* two >> 3, not one >> 2 */
  1270.      + (FaceWindow->GZZWidth >> 3),/* so eyes are same width */
  1271.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1272.  
  1273.     SetAPen(FaceWindow->RPort, REDP);  /* Set pen to Red */
  1274.     Move(FaceWindow->RPort,
  1275.      XMouthCenter - (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1276.     Draw(FaceWindow->RPort,
  1277.      XMouthCenter + (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1278.  
  1279. }
  1280.  
  1281. /* Deallocate any memory, and close all of the
  1282.  * windows/screens/devices/libraries in reverse order to
  1283.  * make things work smoothly. And be sure to check
  1284.  * that the open/allocation was successful before
  1285.  * closing/deallocating.
  1286.  */
  1287. MyCleanup()
  1288. {
  1289.    if (read_port.mp_SigBit != -1)
  1290.       FreeSignal(read_port.mp_SigBit);
  1291.    if (talk_port.mp_SigBit != -1)
  1292.       FreeSignal(talk_port.mp_SigBit);
  1293.    if (FaceWindow != NULL)
  1294.       CloseWindow(FaceWindow);
  1295.    if (ControlWindow != NULL)
  1296.       CloseWindow(ControlWindow);
  1297.    /* freeimages makes sure image allocation was successful */
  1298.    freeimages();
  1299.    if (NarratorOpenError == 0)
  1300.       CloseDevice(&voice_io);
  1301.    if (TranslatorBase != 0)
  1302.       CloseLibrary(TranslatorBase);
  1303.    if (GfxBase != 0)
  1304.       CloseLibrary(GfxBase);
  1305.    if (IntuitionBase != 0)
  1306.       CloseLibrary(IntuitionBase);
  1307.    return(0);
  1308. }
  1309.  
  1310. /* Allocate chip memory for gadget images, and set the
  1311.  * pointers in the corresponding image structures to point
  1312.  * to these images. This must be done because the program
  1313.  * could be loaded into expansion memory (off the side of
  1314.  * the box), which the custom chips cannot access.
  1315.  * And images must be in chip ram (that's memory that the
  1316.  * custom chips can access, the internal 512K).
  1317.  */
  1318. InitImages()
  1319. {
  1320.    /* the images were staticly initialized above main */
  1321.    extern USHORT *FemaleIData_chip;
  1322.    extern USHORT *MaleIData_chip;
  1323.    extern USHORT *HumanIData_chip;
  1324.    extern USHORT *RobotIData_chip;
  1325.    extern USHORT *FaceIData_chip;
  1326.    extern USHORT *StopIData_chip;
  1327.    int i;
  1328.  
  1329.    /* Allocate them all, stop and return false on failure */
  1330.    if ((FemaleIData_chip = (USHORT *)
  1331.     AllocMem(sizeof(FemaleIData),MEMF_CHIP)) == 0)
  1332.       return(FALSE);
  1333.    if ((MaleIData_chip = (USHORT *)
  1334.     AllocMem(sizeof(MaleIData),MEMF_CHIP)) == 0)
  1335.       return(FALSE);
  1336.    if ((HumanIData_chip = (USHORT *)
  1337.     AllocMem(sizeof(HumanIData),MEMF_CHIP)) == 0)
  1338.       return(FALSE);
  1339.    if ((RobotIData_chip = (USHORT *)
  1340.     AllocMem(sizeof(RobotIData),MEMF_CHIP)) == 0)
  1341.       return(FALSE);
  1342.    if ((FaceIData_chip = (USHORT *)
  1343.     AllocMem(sizeof(FaceIData),MEMF_CHIP)) == 0)
  1344.       return(FALSE);
  1345.    if ((StopIData_chip = (USHORT *)
  1346.     AllocMem(sizeof(StopIData),MEMF_CHIP)) == 0)
  1347.       return(FALSE);
  1348.  
  1349.    for (i=0; i<20; i++)
  1350.       FemaleIData_chip[i] = FemaleIData[i];
  1351.    for (i=0; i<20; i++)
  1352.       MaleIData_chip[i] = MaleIData[i];
  1353.    for (i=0; i<60; i++)
  1354.       HumanIData_chip[i] = HumanIData[i];
  1355.    for (i=0; i<60; i++)
  1356.       RobotIData_chip[i] = RobotIData[i];
  1357.    for (i=0; i<30; i++)
  1358.       FaceIData_chip[i] = FaceIData[i];
  1359.    for (i=0; i<30; i++)
  1360.       StopIData_chip[i] = StopIData[i];
  1361.  
  1362.    FemaleImage.ImageData = FemaleIData_chip;
  1363.    MaleImage.ImageData = MaleIData_chip;
  1364.    HumanImage.ImageData = HumanIData_chip;
  1365.    RobotImage.ImageData = RobotIData_chip;
  1366.    FaceImage.ImageData = FaceIData_chip;
  1367.    StopImage.ImageData = StopIData_chip;
  1368.  
  1369.    return(TRUE);
  1370. }
  1371.  
  1372. /* Deallocate the memory that was used for images,
  1373.  * See initimages for more details.
  1374.  */
  1375. freeimages()
  1376. {
  1377.    /* the images were staticly initialized above main */
  1378.    extern USHORT *FemaleIData_chip;
  1379.    extern USHORT *MaleIData_chip;
  1380.    extern USHORT *HumanIData_chip;
  1381.    extern USHORT *RobotIData_chip;
  1382.    extern USHORT *FaceIData_chip;
  1383.    extern USHORT *StopIData_chip;
  1384.  
  1385.    /* Deallocate only if the pointer is really there. */
  1386.    if (RobotIData_chip != 0)
  1387.       FreeMem(RobotIData_chip, sizeof(RobotIData));
  1388.    if (HumanIData_chip != 0)
  1389.       FreeMem(HumanIData_chip, sizeof(HumanIData));
  1390.    if (MaleIData_chip != 0)
  1391.       FreeMem(MaleIData_chip, sizeof(MaleIData));
  1392.    if (FemaleIData_chip != 0)
  1393.       FreeMem(FemaleIData_chip, sizeof(FemaleIData));
  1394.    if (FaceIData_chip != 0)
  1395.       FreeMem(FaceIData_chip, sizeof(FaceIData));
  1396.    if (StopIData_chip != 0)
  1397.       FreeMem(StopIData_chip, sizeof(StopIData));
  1398. }
  1399.